package com.entertainment.ticketing.controller;

import com.entertainment.ticketing.dto.CreateOrderRequest;
import com.entertainment.ticketing.dto.OrderResponse;
import com.entertainment.ticketing.dto.PageResponse;
import com.entertainment.ticketing.service.OrderService;
import com.entertainment.ticketing.dto.BatchRefundRequest;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.entertainment.ticketing.repository.UserInfoRepository;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    private final OrderService orderService;
    private final UserInfoRepository userRepo;

    public OrderController(OrderService orderService, UserInfoRepository userRepo) {
        this.orderService = orderService;
        this.userRepo = userRepo;
    }

    @PostMapping
    public ResponseEntity<OrderResponse> create(
            @Valid @RequestBody CreateOrderRequest req,
            @org.springframework.web.bind.annotation.RequestHeader(value = "Idempotency-Key", required = false) String idempotencyKey
    ) {
        return ResponseEntity.ok(orderService.createOrder(req, idempotencyKey));
    }

    @GetMapping("/{orderNo}")
    public ResponseEntity<OrderResponse> get(@PathVariable String orderNo, Authentication auth) {
        OrderResponse resp = orderService.getByOrderNo(orderNo);
        String username = auth != null ? (String) auth.getPrincipal() : null;
        boolean isAdmin = auth != null && auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).anyMatch(a -> "ROLE_ADMIN".equals(a));
        Long currentUserId = null;
        if (username != null) {
            currentUserId = userRepo.findByUsername(username).map(u -> u.getId()).orElse(null);
        }
        if (!isAdmin && (currentUserId == null || !currentUserId.equals(resp.getUserId()))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "无权限访问该订单");
        }
        return ResponseEntity.ok(resp);
    }

    @PostMapping("/{orderNo}/cancel")
    public ResponseEntity<OrderResponse> cancel(@PathVariable String orderNo, Authentication auth) {
        if (auth == null) {
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "未登录");
        }
        // 权限校验：仅本人或管理员
        OrderResponse resp = orderService.getByOrderNo(orderNo);
        String username = (String) auth.getPrincipal();
        boolean isAdmin = auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).anyMatch(a -> "ROLE_ADMIN".equals(a));
        Long currentUserId = userRepo.findByUsername(username).map(u -> u.getId()).orElse(null);
        if (!isAdmin && (currentUserId == null || !currentUserId.equals(resp.getUserId()))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "无权限取消该订单");
        }
        return ResponseEntity.ok(orderService.cancelOrder(orderNo));
    }

    @PostMapping("/{orderNo}/pay")
    public ResponseEntity<OrderResponse> pay(@PathVariable String orderNo, Authentication auth) {
        if (auth == null) {
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "未登录");
        }
        OrderResponse resp = orderService.getByOrderNo(orderNo);
        String username = (String) auth.getPrincipal();
        boolean isAdmin = auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).anyMatch(a -> "ROLE_ADMIN".equals(a));
        Long currentUserId = userRepo.findByUsername(username).map(u -> u.getId()).orElse(null);
        if (!isAdmin && (currentUserId == null || !currentUserId.equals(resp.getUserId()))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "无权限支付该订单");
        }
        return ResponseEntity.ok(orderService.payOrder(orderNo));
    }

    @GetMapping("/me")
    public ResponseEntity<java.util.List<OrderResponse>> myOrders(Authentication auth) {
        if (auth == null) {
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "未登录");
        }
        String username = (String) auth.getPrincipal();
        return ResponseEntity.ok(orderService.listByUsername(username));
    }

    // 管理端：更新订单状态（仅支持 2=已支付，3=已取消）
    @PutMapping("/{id}/status")
    public ResponseEntity<OrderResponse> updateStatus(
            @PathVariable("id") String idOrOrderNo,
            @RequestBody java.util.Map<String, Object> body,
            Authentication auth
    ) {
        if (auth == null || auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).noneMatch(a -> "ROLE_ADMIN".equals(a))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "仅管理员可更新订单状态");
        }
        Object s = body != null ? body.get("status") : null;
        Byte status = null;
        if (s instanceof Number) {
            status = ((Number) s).byteValue();
        } else if (s instanceof String) {
            try { status = Byte.valueOf((String) s); } catch (Exception ignored) {}
        }
        if (status == null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "缺少或非法的状态值");
        }
        OrderResponse resp = orderService.updateStatusByAdmin(idOrOrderNo, status);
        return ResponseEntity.ok(resp);
    }

    // 管理端：分页列表
    @GetMapping
    public ResponseEntity<PageResponse<OrderResponse>> list(
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam(value = "status", required = false) Byte status,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "eventId", required = false) Long eventId,
            @RequestParam(value = "page", defaultValue = "0") int page,
            @RequestParam(value = "size", defaultValue = "10") int size,
            @RequestParam(value = "sortBy", defaultValue = "createdAt") String sortBy,
            @RequestParam(value = "order", defaultValue = "DESC") String order,
            Authentication auth
    ) {
        // 仅管理员可访问列表
        if (auth == null || auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).noneMatch(a -> "ROLE_ADMIN".equals(a))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "仅管理员可访问订单列表");
        }
        Sort.Direction direction = "ASC".equalsIgnoreCase(order) ? Sort.Direction.ASC : Sort.Direction.DESC;
        PageResponse<OrderResponse> resp = orderService.search(keyword, status, userId, eventId, page, size, sortBy, direction);
        return ResponseEntity.ok(resp);
    }

    // 管理端：导出订单CSV（使用与分页列表相同的过滤参数，最多导出10000条）
    @GetMapping("/export")
    public ResponseEntity<ByteArrayResource> export(
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam(value = "status", required = false) Byte status,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "eventId", required = false) Long eventId,
            @RequestParam(value = "sortBy", defaultValue = "createdAt") String sortBy,
            @RequestParam(value = "order", defaultValue = "DESC") String order,
            Authentication auth
    ) {
        if (auth == null || auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).noneMatch(a -> "ROLE_ADMIN".equals(a))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "仅管理员可导出订单");
        }
        Sort.Direction direction = "ASC".equalsIgnoreCase(order) ? Sort.Direction.ASC : Sort.Direction.DESC;
        PageResponse<OrderResponse> page = orderService.search(keyword, status, userId, eventId, 0, 10000, sortBy, direction);
        StringBuilder sb = new StringBuilder();
        sb.append("orderNo,userId,eventId,totalAmount,ticketCount,status,paymentMethod,paymentTime,contactName,contactPhone,contactEmail,createdAt\n");
        for (OrderResponse r : page.getContent()) {
            sb.append(safe(r.getOrderNo())).append(',')
                    .append(safe(r.getUserId())).append(',')
                    .append(safe(r.getEventId())).append(',')
                    .append(safe(r.getTotalAmount())).append(',')
                    .append(safe(r.getTicketCount())).append(',')
                    .append(safe(r.getStatus())).append(',')
                    .append(safe(r.getPaymentMethod())).append(',')
                    .append(safe(r.getPaymentTime())).append(',')
                    .append(safe(r.getContactName())).append(',')
                    .append(safe(r.getContactPhone())).append(',')
                    .append(safe(r.getContactEmail())).append(',')
                    .append(safe(r.getCreatedAt())).append('\n');
        }
        byte[] bytes = sb.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8);
        ByteArrayResource resource = new ByteArrayResource(bytes);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("text/csv; charset=utf-8"));
        headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=orders.csv");
        return ResponseEntity.ok().headers(headers).body(resource);
    }

    private String safe(Object o) {
        if (o == null) return "";
        String s = String.valueOf(o);
        return s.replaceAll(",", " ").replaceAll("\n|\r", " ");
    }

    // 管理端：批量退款模拟（仅处理已支付订单）
    @PostMapping("/batch/refund")
    public ResponseEntity<java.util.List<OrderResponse>> batchRefund(
            @RequestBody BatchRefundRequest req,
            Authentication auth
    ) {
        if (auth == null || auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).noneMatch(a -> "ROLE_ADMIN".equals(a))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "仅管理员可批量退款");
        }
        java.util.List<String> ids = (req != null && req.getIds() != null) ? req.getIds() : java.util.List.of();
        return ResponseEntity.ok(orderService.batchRefundPaidOrders(ids));
    }

}